 /*******************************************************************************
  * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
  * http://www.eclipse.org/legal/epl-v10.html
  *
  * Contributors:
  * IBM Corporation - initial API and implementation
  * Sebastian Davids <sdavids@gmx.de> - Collapse all action (25826)
  * Sebastian Davids <sdavids@gmx.de> - Images for menu items (27481)
  *******************************************************************************/
 package org.eclipse.ui.views.navigator;

 import java.util.List ;

 import org.eclipse.core.commands.operations.IUndoContext;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
 import org.eclipse.core.resources.IResourceChangeListener;
 import org.eclipse.core.resources.IResourceDelta;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.jface.action.IMenuManager;
 import org.eclipse.jface.action.IToolBarManager;
 import org.eclipse.jface.action.MenuManager;
 import org.eclipse.jface.action.Separator;
 import org.eclipse.jface.util.IPropertyChangeListener;
 import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.swt.events.KeyEvent;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IWorkbenchActionConstants;
 import org.eclipse.ui.IWorkingSet;
 import org.eclipse.ui.actions.ActionContext;
 import org.eclipse.ui.actions.ActionFactory;
 import org.eclipse.ui.actions.AddBookmarkAction;
 import org.eclipse.ui.actions.AddTaskAction;
 import org.eclipse.ui.actions.ExportResourcesAction;
 import org.eclipse.ui.actions.ImportResourcesAction;
 import org.eclipse.ui.actions.NewWizardMenu;
 import org.eclipse.ui.actions.WorkingSetFilterActionGroup;
 import org.eclipse.ui.dialogs.PropertyDialogAction;
 import org.eclipse.ui.ide.IDEActionFactory;
 import org.eclipse.ui.internal.views.navigator.ResourceNavigatorMessages;
 import org.eclipse.ui.operations.UndoRedoActionGroup;

 /**
  * The main action group for the navigator.
  * This contains a few actions and several subgroups.
  */
 public class MainActionGroup extends ResourceNavigatorActionGroup {

     protected AddBookmarkAction addBookmarkAction;

     protected AddTaskAction addTaskAction;

     protected PropertyDialogAction propertyDialogAction;

     protected ImportResourcesAction importAction;
     
     protected ExportResourcesAction exportAction;

     protected CollapseAllAction collapseAllAction;

     protected ToggleLinkingAction toggleLinkingAction;

     protected GotoActionGroup gotoGroup;

     protected OpenActionGroup openGroup;

     protected RefactorActionGroup refactorGroup;

     protected WorkingSetFilterActionGroup workingSetGroup;

     protected SortAndFilterActionGroup sortAndFilterGroup;
     
     protected UndoRedoActionGroup undoRedoGroup;

     protected WorkspaceActionGroup workspaceGroup;

     private IResourceChangeListener resourceChangeListener;

     private NewWizardMenu newWizardMenu;

     /**
      * Constructs the main action group.
      *
      * @param navigator the navigator view
      */
     public MainActionGroup(IResourceNavigator navigator) {
         super(navigator);
         resourceChangeListener = new IResourceChangeListener() {
             public void resourceChanged(IResourceChangeEvent event) {
                 handleResourceChanged(event);
             }
         };
         ResourcesPlugin.getWorkspace().addResourceChangeListener(
                 resourceChangeListener, IResourceChangeEvent.POST_CHANGE);
         makeSubGroups();
     }

     /**
      * Handles a resource changed event by updating the enablement
      * if one of the selected projects is opened or closed.
      */
     protected void handleResourceChanged(IResourceChangeEvent event) {
         ActionContext context = getContext();
         if (context == null) {
             return;
         }

         final IStructuredSelection selection = (IStructuredSelection) context
                 .getSelection();
         if (ResourceSelectionUtil.allResourcesAreOfType(selection,
                 IResource.PROJECT) == false) {
             return;
         }
         List sel = selection.toList();
         IResourceDelta delta = event.getDelta();
         if (delta == null) {
             return;
         }
         IResourceDelta[] projDeltas = delta
                 .getAffectedChildren(IResourceDelta.CHANGED);
         for (int i = 0; i < projDeltas.length; ++i) {
             IResourceDelta projDelta = projDeltas[i];
             //changing the project open state or description will effect open/close/build action enablement
 if ((projDelta.getFlags() & (IResourceDelta.OPEN | IResourceDelta.DESCRIPTION)) != 0) {
                 if (sel.contains(projDelta.getResource())) {
                     getNavigator().getSite().getShell().getDisplay().syncExec(
                             new Runnable () {
                                 public void run() {
                                     addTaskAction.selectionChanged(selection);
                                     gotoGroup.updateActionBars();
                                     refactorGroup.updateActionBars();
                                     workspaceGroup.updateActionBars();
                                 }
                             });
                 }
             }
         }
     }

     /**
      * Makes the actions contained directly in this action group.
      */
     protected void makeActions() {
         Shell shell = navigator.getSite().getShell();

         newWizardMenu = new NewWizardMenu(navigator.getSite().getWorkbenchWindow());
         addBookmarkAction = new AddBookmarkAction(shell);
         addTaskAction = new AddTaskAction(shell);
         propertyDialogAction = new PropertyDialogAction(shell, navigator
                 .getViewer());

         importAction = new ImportResourcesAction(navigator.getSite()
                 .getWorkbenchWindow());
         importAction
                 .setDisabledImageDescriptor(getImageDescriptor("dtool16/import_wiz.gif")); //$NON-NLS-1$
 importAction
                 .setImageDescriptor(getImageDescriptor("etool16/import_wiz.gif")); //$NON-NLS-1$

         exportAction = new ExportResourcesAction(navigator.getSite()
                 .getWorkbenchWindow());
         exportAction
                 .setDisabledImageDescriptor(getImageDescriptor("dtool16/export_wiz.gif")); //$NON-NLS-1$
 exportAction
                 .setImageDescriptor(getImageDescriptor("etool16/export_wiz.gif")); //$NON-NLS-1$

         
         collapseAllAction = new CollapseAllAction(navigator,
                 ResourceNavigatorMessages.CollapseAllAction_title);
         collapseAllAction.setToolTipText(ResourceNavigatorMessages.CollapseAllAction_toolTip);
         collapseAllAction
                 .setImageDescriptor(getImageDescriptor("elcl16/collapseall.gif")); //$NON-NLS-1$

         toggleLinkingAction = new ToggleLinkingAction(navigator,
                 ResourceNavigatorMessages.ToggleLinkingAction_text);
         toggleLinkingAction.setToolTipText(ResourceNavigatorMessages.ToggleLinkingAction_toolTip);
         toggleLinkingAction
                 .setImageDescriptor(getImageDescriptor("elcl16/synced.gif"));//$NON-NLS-1$
 }

     /**
      * Makes the sub action groups.
      */
     protected void makeSubGroups() {
         gotoGroup = new GotoActionGroup(navigator);
         openGroup = new OpenActionGroup(navigator);
         refactorGroup = new RefactorActionGroup(navigator);
         IPropertyChangeListener workingSetUpdater = new IPropertyChangeListener() {
             public void propertyChange(PropertyChangeEvent event) {
                 String property = event.getProperty();

                 if (WorkingSetFilterActionGroup.CHANGE_WORKING_SET
                         .equals(property)) {
                     IResourceNavigator navigator = getNavigator();
                     Object newValue = event.getNewValue();

                     if (newValue instanceof IWorkingSet) {
                         navigator.setWorkingSet((IWorkingSet) newValue);
                     } else if (newValue == null) {
                         navigator.setWorkingSet(null);
                     }
                 }
             }
         };
         TreeViewer treeView = navigator.getViewer();
         Shell shell = treeView.getControl().getShell();
         workingSetGroup = new WorkingSetFilterActionGroup(shell,
                 workingSetUpdater);
         workingSetGroup.setWorkingSet(navigator.getWorkingSet());
         sortAndFilterGroup = new SortAndFilterActionGroup(navigator);
         workspaceGroup = new WorkspaceActionGroup(navigator);
         IUndoContext workspaceContext= (IUndoContext)ResourcesPlugin.getWorkspace().getAdapter(IUndoContext.class);
         undoRedoGroup= new UndoRedoActionGroup(getNavigator().getSite(), workspaceContext, true);

     }
     
     /**
      * Extends the superclass implementation to set the context in the subgroups.
      */
     public void setContext(ActionContext context) {
         super.setContext(context);
         gotoGroup.setContext(context);
         openGroup.setContext(context);
         refactorGroup.setContext(context);
         sortAndFilterGroup.setContext(context);
         workspaceGroup.setContext(context);
         undoRedoGroup.setContext(context);
     }

     /**
      * Fills the context menu with the actions contained in this group
      * and its subgroups.
      *
      * @param menu the context menu
      */
     public void fillContextMenu(IMenuManager menu) {
         IStructuredSelection selection = (IStructuredSelection) getContext()
                 .getSelection();

         MenuManager newMenu = new MenuManager(ResourceNavigatorMessages.ResourceNavigator_new);
         menu.add(newMenu);
         newMenu.add(newWizardMenu);

         gotoGroup.fillContextMenu(menu);
         openGroup.fillContextMenu(menu);
         menu.add(new Separator());

         refactorGroup.fillContextMenu(menu);
         menu.add(new Separator());

         menu.add(importAction);
         menu.add(exportAction);
         importAction.selectionChanged(selection);
         exportAction.selectionChanged(selection);
         menu.add(new Separator());

         workspaceGroup.fillContextMenu(menu);

         menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
         menu
                 .add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS
                         + "-end")); //$NON-NLS-1$
 menu.add(new Separator());

         if (selection.size() == 1) {
             propertyDialogAction.selectionChanged(selection);
             menu.add(propertyDialogAction);
         }
     }

     /**
      * Adds the actions in this group and its subgroups to the action bars.
      */
     public void fillActionBars(IActionBars actionBars) {
         actionBars.setGlobalActionHandler(ActionFactory.PROPERTIES.getId(),
                 propertyDialogAction);
         actionBars.setGlobalActionHandler(IDEActionFactory.BOOKMARK.getId(),
                 addBookmarkAction);
         actionBars.setGlobalActionHandler(IDEActionFactory.ADD_TASK.getId(),
                 addTaskAction);

         gotoGroup.fillActionBars(actionBars);
         openGroup.fillActionBars(actionBars);
         refactorGroup.fillActionBars(actionBars);
         workingSetGroup.fillActionBars(actionBars);
         sortAndFilterGroup.fillActionBars(actionBars);
         workspaceGroup.fillActionBars(actionBars);
         undoRedoGroup.fillActionBars(actionBars);

         IMenuManager menu = actionBars.getMenuManager();
         menu.add(toggleLinkingAction);

         IToolBarManager toolBar = actionBars.getToolBarManager();
         toolBar.add(new Separator());
         toolBar.add(collapseAllAction);
         toolBar.add(toggleLinkingAction);
     }

     /**
      * Updates the actions which were added to the action bars,
      * delegating to the subgroups as necessary.
      */
     public void updateActionBars() {
         IStructuredSelection selection = (IStructuredSelection) getContext()
                 .getSelection();
         propertyDialogAction.setEnabled(selection.size() == 1);
         addBookmarkAction.selectionChanged(selection);
         addTaskAction.selectionChanged(selection);

         gotoGroup.updateActionBars();
         openGroup.updateActionBars();
         refactorGroup.updateActionBars();
         workingSetGroup.updateActionBars();
         sortAndFilterGroup.updateActionBars();
         workspaceGroup.updateActionBars();
         undoRedoGroup.updateActionBars();
     }

     /**
      * Runs the default action (open file) by delegating the open group.
      */
     public void runDefaultAction(IStructuredSelection selection) {
         openGroup.runDefaultAction(selection);
     }

     /**
      * Handles a key pressed event by invoking the appropriate action,
      * delegating to the subgroups as necessary.
      */
     public void handleKeyPressed(KeyEvent event) {
         refactorGroup.handleKeyPressed(event);
         workspaceGroup.handleKeyPressed(event);
     }

     /**
      * Extends the superclass implementation to dispose the
      * actions in this group and its subgroups.
      */
     public void dispose() {
         ResourcesPlugin.getWorkspace().removeResourceChangeListener(
                 resourceChangeListener);

         newWizardMenu.dispose();
         collapseAllAction.dispose();
         importAction.dispose();
         exportAction.dispose();
         propertyDialogAction.dispose();
         toggleLinkingAction.dispose();

         gotoGroup.dispose();
         openGroup.dispose();
         refactorGroup.dispose();
         sortAndFilterGroup.dispose();
         workingSetGroup.dispose();
         workspaceGroup.dispose();
         undoRedoGroup.dispose();
         super.dispose();
     }
 }

